package com.lekang.web.controller.system;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lekang.common.annotation.Anonymous;
import com.lekang.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.lekang.common.constant.Constants;
import com.lekang.common.core.domain.AjaxResult;
import com.lekang.common.core.domain.entity.SysMenu;
import com.lekang.common.core.domain.entity.SysUser;
import com.lekang.common.core.domain.model.LoginBody;
import com.lekang.common.core.domain.model.LoginUser;
import com.lekang.common.core.text.Convert;
import com.lekang.common.utils.DateUtils;
import com.lekang.common.utils.SecurityUtils;
import com.lekang.common.utils.StringUtils;
import com.lekang.framework.web.service.SysLoginService;
import com.lekang.framework.web.service.SysPermissionService;
import com.lekang.framework.web.service.TokenService;
import com.lekang.system.service.ISysConfigService;
import com.lekang.system.service.ISysMenuService;

/**
 * 登录验证
 *
 * @author lekang
 */
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    // 微信配置
    private static final String APP_ID = "wxc7f5a7d968b31ff5";
    private static final String APP_SECRET = "835128adce73ec744400337bdfa7fa74";
    private static final String ACCESS_TOKEN_URL =
            "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    private static final String GET_PHONE_NUMBER_URL =
            "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";

    /**
     * 微信授权登录接口
     */
    @PostMapping("/wxphoneLogin")
    @Anonymous
    public AjaxResult getwxPhoneNumber(@RequestBody PhoneCodeRequest request) {
        String code = request.getCode();
        System.out.println("=== 开始微信登录处理 ===");
        System.out.println("接收到的code: " + code);

        try {
            // 1. 先获取 access_token
            System.out.println("开始获取access_token...");
            String accessToken = getAccessToken();
            System.out.println("获取到access_token: " + accessToken);

            // 2. 调用获取手机号接口
            String phoneApiUrl = String.format(GET_PHONE_NUMBER_URL, accessToken);
            String jsonBody = String.format("{\"code\":\"%s\"}", code);

            System.out.println("调用微信手机号API: " + phoneApiUrl);

            HttpClient httpClient = HttpClient.newHttpClient();
            HttpRequest httpRequest = HttpRequest.newBuilder()
                    .uri(URI.create(phoneApiUrl))
                    .header("Content-Type", "application/json; charset=utf-8")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

            HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

            // 3. 解析微信返回结果
            System.out.println("微信返回原始数据：" + response.body());
            String body = response.body();

            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(body);

            // 检查微信API是否返回错误
            if (rootNode.has("errcode") && rootNode.get("errcode").asInt() != 0) {
                System.err.println("微信API错误: " + rootNode.get("errcode").asInt() + " - " + rootNode.get("errmsg").asText());
                return AjaxResult.error("微信API错误: " + rootNode.get("errmsg").asText());
            }

            JsonNode phoneInfoNode = rootNode.path("phone_info");
            String phoneNumber = phoneInfoNode.path("phoneNumber").asText();
            System.out.println("解析到的手机号：" + phoneNumber);

            if (StringUtils.isEmpty(phoneNumber)) {
                System.err.println("未能获取到手机号");
                return AjaxResult.error("未能获取到手机号");
            }

            // 4. 处理登录
            System.out.println("开始处理用户登录...");
            SysUser user = sysUserService.selectUserByUserName(phoneNumber);

            System.out.println("生成token...");
            String token = loginService.wxlogin(phoneNumber);
            System.out.println("生成的token: " + token);

            Map<String, Object> data = new HashMap<>();
            data.put(Constants.TOKEN, token);
            data.put("phoneNumber", phoneNumber);

            // 新增：返回用户昵称
            if (user != null) {
                data.put("name", user.getNickName());
            } else {
                // 注册时生成默认昵称（手机号后4位）
                String nickName = "微信用户" + phoneNumber.substring(phoneNumber.length() - 4);
                data.put("name", nickName);
            }

            if (user != null) {
                System.out.println("用户已存在，直接登录");
                return AjaxResult.success(data);
            } else {
                System.out.println("用户不存在，开始注册");
                SysUser sysUser = new SysUser();
                sysUser.setUserName(phoneNumber);
                sysUser.setPhonenumber(phoneNumber);
                sysUser.setNickName("微信用户" + phoneNumber.substring(phoneNumber.length() - 4)); // 注册时设置昵称
                sysUser.setPassword(passwordEncoder.encode("123456"));
                sysUser.setRoleIds(new Long[]{101L});

                System.out.println("插入用户到数据库...");
                sysUserService.insertUser(sysUser);
                System.out.println("用户注册成功");

                return AjaxResult.success(data);
            }

        } catch (Exception e) {
            System.err.println("=== 微信登录异常 ===");
            e.printStackTrace();
            System.err.println("异常信息: " + e.getMessage());
            return AjaxResult.error("微信登录失败：" + e.getMessage());
        }
    }

    /**
     * 手动输入手机号登录接口
     */
    @PostMapping("/phoneLogin")
    @Anonymous
    public AjaxResult getPhoneNumber(@RequestBody PhoneCodeRequest request) {
        String phoneNumber = request.getCode();
        try {
            // 验证手机号格式
            if (!isValidPhoneNumber(phoneNumber)) {
                return AjaxResult.error("手机号格式不正确");
            }

            // 统一的登录处理
            return processLogin(phoneNumber, 2L);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("登录失败：" + e.getMessage());
        }
    }

    /**
     * 统一的登录处理逻辑
     */
    private AjaxResult processLogin(String phoneNumber, Long roleId) {
        try {
            // 1. 用手机号查询用户
            SysUser user = sysUserService.selectUserByUserName(phoneNumber);

            // 2. 生成令牌
            String token = loginService.wxlogin(phoneNumber);

            // 3. 构造返回数据
            Map<String, Object> data = new HashMap<>();
            data.put(Constants.TOKEN, token);
            data.put("phoneNumber", phoneNumber);

            // 新增：返回用户昵称
            if (user != null) {
                data.put("name", user.getNickName());
            } else {
                String nickName = "用户" + phoneNumber.substring(phoneNumber.length() - 4);
                data.put("name", nickName);
            }

            // 4. 存在用户则直接登录，不存在则注册后登录
            if (user != null) {
                System.out.println("直接登录：用户已存在，user_name=" + phoneNumber);
                return AjaxResult.success(data);
            } else {
                System.out.println("注册后登录：用户不存在，开始创建用户");
                SysUser newUser = new SysUser();
                newUser.setUserName(phoneNumber);
                newUser.setPhonenumber(phoneNumber);

                // 生成昵称
                String nickName = "用户" + phoneNumber.substring(phoneNumber.length() - 4);
                newUser.setNickName(nickName);

                newUser.setPassword(passwordEncoder.encode("123456"));
                newUser.setRoleIds(new Long[]{roleId});
                sysUserService.insertUser(newUser);
                return AjaxResult.success(data);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("登录处理失败：" + e.getMessage());
        }
    }

    /**
     * 获取 access_token（小程序全局凭证）
     */
    private String getAccessToken() throws Exception {
        String url = String.format(ACCESS_TOKEN_URL, APP_ID, APP_SECRET);

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .GET()
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

        System.out.println("access_token 接口返回：" + response.body());

        // 使用 Jackson 正确解析 JSON
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = objectMapper.readTree(response.body());
        String token = rootNode.path("access_token").asText();

        if (StringUtils.isNotEmpty(token)) {
            return token;
        }

        throw new RuntimeException("无法获取 access_token：" + response.body());
    }

    /**
     * 验证手机号格式
     */
    private boolean isValidPhoneNumber(String phone) {
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }

    /**
     * 用于接收前端传来的 code
     */
    public static class PhoneCodeRequest {
        private String code;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }
    }

    /**
     * 登录方法
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 微信登录方法
     */
    @GetMapping("/wxlogin")
    public AjaxResult wxlogin(String phone) {
        AjaxResult ajax = AjaxResult.success();
        String token = loginService.wxlogin(phone);
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 获取微信用户信息
     */
    @GetMapping("/getwxInfo")
    public AjaxResult getwxInfo() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        Set<String> roles = permissionService.getRolePermission(user);
        Set<String> permissions = permissionService.getMenuPermission(user);
        if (!loginUser.getPermissions().equals(permissions)) {
            loginUser.setPermissions(permissions);
            tokenService.refreshToken(loginUser);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
        ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
        return ajax;
    }

    /**
     * 获取用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        Set<String> roles = permissionService.getRolePermission(user);
        Set<String> permissions = permissionService.getMenuPermission(user);
        if (!loginUser.getPermissions().equals(permissions)) {
            loginUser.setPermissions(permissions);
            tokenService.refreshToken(loginUser);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
        ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
        return ajax;
    }

    /**
     * 获取路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters() {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    /**
     * 检查初始密码是否提醒修改
     */
    public boolean initPasswordIsModify(Date pwdUpdateDate) {
        Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
        return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
    }

    /**
     * 检查密码是否过期
     */
    public boolean passwordIsExpiration(Date pwdUpdateDate) {
        Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
        if (passwordValidateDays != null && passwordValidateDays > 0) {
            if (StringUtils.isNull(pwdUpdateDate)) {
                return true;
            }
            Date nowDate = DateUtils.getNowDate();
            return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
        }
        return false;
    }
}